[HVM] Add a concept of HVM parameters to the hypervisor.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 3 Aug 2006 12:53:33 +0000 (13:53 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 3 Aug 2006 12:53:33 +0000 (13:53 +0100)
Each HVM domain has a space of HVM parameters associated with it,
and these can be manipulated via a new hvm_op hypercall. This means
that the hypervisor no longer needs to parse the hvm_info table, so
remove that code.

Signed-off-by: Steven Smith <ssmith@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
tools/libxc/xc_hvm_build.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_64/entry.S
xen/include/asm-x86/hvm/domain.h
xen/include/public/xen.h
xen/include/xen/hypercall.h

index d367c6930025d070558cddd5cf054850ca18521c..3c9bb9f0d2d60c0c7c8db8b11b3ef38f5b5c7381 100644 (file)
@@ -270,6 +270,7 @@ static int __init privcmd_init(void)
        set_bit(__HYPERVISOR_sched_op_compat,  hypercall_permission_map);
        set_bit(__HYPERVISOR_event_channel_op_compat,
                hypercall_permission_map);
+       set_bit(__HYPERVISOR_hvm_op,           hypercall_permission_map);
 
        privcmd_intf = create_xen_proc_entry("privcmd", 0400);
        if (privcmd_intf != NULL)
index 724b37c4c49095cf09f7a0adef721f21490749e7..bdfb1cf976b9b2d0b4613ddf4b5dac1968086449 100644 (file)
@@ -6,12 +6,14 @@
 #include <stddef.h>
 #include <inttypes.h>
 #include "xg_private.h"
+#include "xc_private.h"
 #include "xc_elf.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <zlib.h>
 #include <xen/hvm/hvm_info_table.h>
 #include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
 
 #define HVM_LOADER_ENTR_ADDR  0x00100000
 
@@ -43,6 +45,30 @@ loadelfimage(
     char *elfbase, int xch, uint32_t dom, unsigned long *parray,
     struct domain_setup_info *dsi);
 
+static void xc_set_hvm_param(int handle,
+                             domid_t dom, int param, unsigned long value)
+{
+    DECLARE_HYPERCALL;
+    xen_hvm_param_t arg;
+    int rc;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_param;
+    hypercall.arg[1] = (unsigned long)&arg;
+    arg.domid = dom;
+    arg.index = param;
+    arg.value = value;
+    if ( mlock(&arg, sizeof(arg)) != 0 )
+    {
+        PERROR("Could not lock memory for set parameter");
+        return;
+    }
+    rc = do_xen_hypercall(handle, &hypercall);
+    safe_munlock(&arg, sizeof(arg));
+    if (rc < 0)
+        PERROR("set HVM parameter failed (%d)", rc);
+}
+
 static void build_e820map(void *e820_page, unsigned long long mem_size)
 {
     struct e820entry *e820entry =
@@ -154,6 +180,9 @@ static int set_hvm_info(int xc_handle, uint32_t dom,
 
     munmap(va_map, PAGE_SIZE);
 
+    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_APIC_ENABLED, apic);
+    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
+
     return 0;
 }
 
@@ -287,6 +316,9 @@ static int setup_guest(int xc_handle,
 
     munmap(sp, PAGE_SIZE);
 
+    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, (v_end >> PAGE_SHIFT) - 2);
+    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
+
     *store_mfn = page_array[(v_end >> PAGE_SHIFT) - 2];
     if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) )
         goto error_out;
index 4120505a8b3c813c2014d6854efb5ff8e3863cee..9fcd17be41ab5df321f988086459f00b23822b06 100644 (file)
@@ -46,6 +46,7 @@
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
 #include <public/hvm/hvm_info_table.h>
+#include <xen/guest_access.h>
 
 int hvm_enabled = 0;
 
@@ -128,61 +129,6 @@ static void hvm_map_io_shared_page(struct domain *d)
     d->arch.hvm_domain.shared_page_va = (unsigned long)p;
 }
 
-static int validate_hvm_info(struct hvm_info_table *t)
-{
-    char signature[] = "HVM INFO";
-    uint8_t *ptr = (uint8_t *)t;
-    uint8_t sum = 0;
-    int i;
-
-    /* strncmp(t->signature, "HVM INFO", 8) */
-    for ( i = 0; i < 8; i++ ) {
-        if ( signature[i] != t->signature[i] ) {
-            printk("Bad hvm info signature\n");
-            return 0;
-        }
-    }
-
-    for ( i = 0; i < t->length; i++ )
-        sum += ptr[i];
-
-    return (sum == 0);
-}
-
-static void hvm_get_info(struct domain *d)
-{
-    unsigned char *p;
-    unsigned long mfn;
-    struct hvm_info_table *t;
-
-    mfn = get_mfn_from_gpfn(HVM_INFO_PFN);
-    if ( mfn == INVALID_MFN ) {
-        printk("Can not get info page mfn for HVM domain.\n");
-        domain_crash_synchronous();
-    }
-
-    p = map_domain_page(mfn);
-    if ( p == NULL ) {
-        printk("Can not map info page for HVM domain.\n");
-        domain_crash_synchronous();
-    }
-
-    t = (struct hvm_info_table *)(p + HVM_INFO_OFFSET);
-
-    if ( validate_hvm_info(t) ) {
-        d->arch.hvm_domain.nr_vcpus = t->nr_vcpus;
-        d->arch.hvm_domain.apic_enabled = t->apic_enabled;
-        d->arch.hvm_domain.pae_enabled = t->pae_enabled;
-    } else {
-        printk("Bad hvm info table\n");
-        d->arch.hvm_domain.nr_vcpus = 1;
-        d->arch.hvm_domain.apic_enabled = 0;
-        d->arch.hvm_domain.pae_enabled = 0;
-    }
-
-    unmap_domain_page(p);
-}
-
 void hvm_setup_platform(struct domain* d)
 {
     struct hvm_domain *platform;
@@ -198,7 +144,6 @@ void hvm_setup_platform(struct domain* d)
     }
 
     hvm_map_io_shared_page(d);
-    hvm_get_info(d);
 
     platform = &d->arch.hvm_domain;
     pic_init(&platform->vpic, pic_irq_request, &platform->interrupt_request);
@@ -343,8 +288,8 @@ static hvm_hypercall_t *hvm_hypercall_table[] = {
     HYPERCALL(event_channel_op_compat),
     HYPERCALL(xen_version),
     HYPERCALL(grant_table_op),
-    HYPERCALL(event_channel_op)
-    /*HYPERCALL(hvm_op)*/
+    HYPERCALL(event_channel_op),
+    HYPERCALL(hvm_op)
 };
 #undef HYPERCALL
 
@@ -435,6 +380,65 @@ int hvm_bringup_ap(int vcpuid, int trampoline_vector)
     return rc;
 }
 
+long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
+
+{
+    long rc = 0;
+
+    switch ( op )
+    {
+    case HVMOP_set_param:
+    case HVMOP_get_param:
+    {
+        struct xen_hvm_param a;
+        struct domain *d;
+
+        if ( copy_from_guest(&a, arg, 1) )
+            return -EFAULT;
+
+        if ( a.index >= HVM_NR_PARAMS )
+            return -EINVAL;
+
+        if ( a.domid == DOMID_SELF )
+        {
+            get_knownalive_domain(current->domain);
+            d = current->domain;
+        }
+        else if ( IS_PRIV(current->domain) )
+        {
+            d = find_domain_by_id(a.domid);
+            if ( !d )
+                return -ESRCH;
+        }
+        else
+        {
+            return -EPERM;
+        }
+
+        if ( op == HVMOP_set_param )
+        {
+            rc = 0;
+            d->arch.hvm_domain.params[a.index] = a.value;
+        }
+        else
+        {
+            rc = d->arch.hvm_domain.params[a.index];
+        }
+
+        put_domain(d);
+        return rc;
+    }
+
+    default:
+    {
+        DPRINTK("Bad HVM op %ld.\n", op);
+        rc = -ENOSYS;
+    }
+    }
+
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
index bb16553f5538520d0bfbf731ae468bf7b9ff8e9d..56805dda267905259bf244b26c90a35ca7ab4cba 100644 (file)
@@ -997,7 +997,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
 #else
         if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
         {
-            if ( !v->domain->arch.hvm_domain.pae_enabled )
+            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
                 clear_bit(X86_FEATURE_PAE, &edx);
             clear_bit(X86_FEATURE_PSE, &edx);
             clear_bit(X86_FEATURE_PSE36, &edx);
@@ -1060,7 +1060,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
 #else
         if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
         {
-            if ( !v->domain->arch.hvm_domain.pae_enabled )
+            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
             {
                 clear_bit(X86_FEATURE_NX & 31, &edx);
                 clear_bit(X86_FEATURE_PAE, &edx);
index d87be427bb29bf7ede4d37053570e6d24f616367..700a516b4d44fccc1a11f10883f274433e29f507 100644 (file)
@@ -33,6 +33,7 @@
 #include <xen/sched.h>
 #include <asm/current.h>
 #include <public/hvm/ioreq.h>
+#include <public/hvm/params.h>
 
 /* XXX remove this definition after GFW enabled */
 #define VLAPIC_NO_BIOS
@@ -57,7 +58,7 @@ static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
 
 int hvm_apic_support(struct domain *d)
 {
-    return d->arch.hvm_domain.apic_enabled;
+    return d->arch.hvm_domain.params[HVM_PARAM_APIC_ENABLED];
 }
 
 int vlapic_find_highest_irr(struct vlapic *vlapic)
index 292fdab4ddbd0f0cad05da53fd6068c3548af142..b13f06767542a40cefaa93b18f49b6f322f0c215 100644 (file)
@@ -929,7 +929,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
 #else
             if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
             {
-                if ( v->domain->arch.hvm_domain.pae_enabled )
+                if ( v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
                     clear_bit(X86_FEATURE_PSE36, &edx);
                 else
                 {
index 71cbe20f68503049d0fd4899a182602dfc1d3f52..6b9980fd7aacbb14e7d856fcf95fa7f5f2b9cf15 100644 (file)
@@ -656,6 +656,7 @@ ENTRY(hypercall_table)
         .long do_xenoprof_op
         .long do_event_channel_op
         .long do_physdev_op
+        .long do_hvm_op             /* 34 */
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
@@ -695,6 +696,7 @@ ENTRY(hypercall_args_table)
         .byte 2 /* do_xenoprof_op       */
         .byte 2 /* do_event_channel_op  */
         .byte 2 /* do_physdev_op        */
+        .byte 2 /* do_hvm_op            */  /* 34 */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 2318ec9bbcbd3a224cc4fb2416f80087cbfee079..9680530f43ec59e2dda60be22bc27b49c4690a22 100644 (file)
@@ -568,6 +568,7 @@ ENTRY(hypercall_table)
         .quad do_xenoprof_op
         .quad do_event_channel_op
         .quad do_physdev_op
+        .quad do_hvm_op
         .rept NR_hypercalls-((.-hypercall_table)/8)
         .quad do_ni_hypercall
         .endr
@@ -607,6 +608,7 @@ ENTRY(hypercall_args_table)
         .byte 2 /* do_xenoprof_op       */
         .byte 2 /* do_event_channel_op  */
         .byte 2 /* do_physdev_op        */
+        .byte 2 /* do_hvm_op            */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 78829b59ea2c8feeaf5f7bd50a76337ba1b9088c..2d1d977c41887c1b5b8944cfdc8285195effe016 100644 (file)
 #include <asm/hvm/vpit.h>
 #include <asm/hvm/vlapic.h>
 #include <asm/hvm/vioapic.h>
+#include <public/hvm/params.h>
 
 #define HVM_PBUF_SIZE   80
 
 struct hvm_domain {
     unsigned long          shared_page_va;
-    unsigned int           nr_vcpus;
-    unsigned int           apic_enabled;
-    unsigned int           pae_enabled;
     s64                    tsc_frequency;
     struct pl_time         pl_time;
-    
+
     struct hvm_virpic      vpic;
     struct hvm_vioapic     vioapic;
     struct hvm_io_handler  io_handler;
@@ -48,6 +46,8 @@ struct hvm_domain {
 
     int                    pbuf_index;
     char                   pbuf[HVM_PBUF_SIZE];
+
+    uint64_t               params[HVM_NR_PARAMS];
 };
 
 #endif /* __ASM_X86_HVM_DOMAIN_H__ */
index b3ab26ed1dbc6c861712bdad4cb70d3446af429c..57d5895b9eef976b73dba0adc5230f29a87368db 100644 (file)
@@ -66,6 +66,7 @@
 #define __HYPERVISOR_xenoprof_op          31
 #define __HYPERVISOR_event_channel_op     32
 #define __HYPERVISOR_physdev_op           33
+#define __HYPERVISOR_hvm_op               34
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
index 763819170d8730b08c2735bc02698992111bd7a8..5635fa1961cefa79e103f15769a1cf0ff3818f9c 100644 (file)
@@ -87,4 +87,9 @@ do_nmi_op(
     unsigned int cmd,
     XEN_GUEST_HANDLE(void) arg);
 
+extern long
+do_hvm_op(
+    unsigned long op,
+    XEN_GUEST_HANDLE(void) arg);
+
 #endif /* __XEN_HYPERCALL_H__ */